﻿namespace FBlog.UnitTests.Common

open System
open Xunit

open FBlog.Core

type EnvironmentMock(user, time) =
    let mutable currentUser = user
    let mutable currentTime = time

    member e.SetUser(user) = currentUser <- user
    member e.SetTime(time) = currentTime <- time

    interface IEnvironment with
        member i.CurrentUser with get() = currentUser
        member i.CurrentTime with get() = currentTime

type BlogPostRepositoryMock() =
    let store = new System.Collections.Generic.Dictionary<_,_>()

    interface IBlogPostRepository with
        member i.Load(id) =
            match store.TryGetValue(id) with
            | (false, _) -> None
            | (true, value) -> Some value
        member i.Save(post) = store.[post.Id] <- post
    interface IDisposable with member i.Dispose() = ()
    
module BlogTester =
    
    let testSubject = "once upon a time there was this post"
    let testBody = "as if the body realy mattered here ..."
    let testTags = Seq.singleton "Test"

    let testAuthor = "Carsten König"
    let testPublishTime = DateTime.Now.AddMinutes(-10.0)

    let createTestBlog(testEnvironment, testBlogPostRep) = new Blog(testEnvironment, testBlogPostRep)
    let createTestPost() = new BlogPost(subject = testSubject, rawBody = testBody, tags = testTags)

    let publishTestPos(blog : Blog) =
        let post = createTestPost()
        blog.Publish(post)
        post
        
    let loadPostFromRepository(testBlogPostRep, id) = (testBlogPostRep :> IBlogPostRepository).Load(id)

    let assertTestPublishInfo(info : BlogPublishInfo, lastChange) =
        Assert.False(info.IsEmpty)
        Assert.Equal(testAuthor, info.Author)
        Assert.Equal(testPublishTime, info.PublishTime)
        Assert.Equal(lastChange, info.LastChangeTime)

    let assertPostData(post : BlogPost option, lastChange) = 
        Assert.True(post.IsSome)
        post |> Option.iter
                (fun post ->
                    Assert.Equal(testSubject, post.Subject)
                    Assert.Equal(testBody, post.RawBody)
                    Assert.True((Set.ofSeq testTags) = (Set.ofSeq post.Tags))
                    assertTestPublishInfo (post.PublishInfo, lastChange)                    
                )